#ifndef PLAYER_H___
#define PLAYER_H___

class Player;

#include "Prereqs.h"
#include "GameSession.h"
#include "ReplayRecorder.h"
#include "InputDevice.h"

/*
 * Class to handle anything specific to a player
 */
class Player
{  
public:
    Player(Ball *b, std::vector<MovingObject*> mos, std::vector<OgreNewt::Body*> aos, 
           TeleportControl *tc, PickupControl* p, ScoreObjectControl *soc, ScoreToppleControl *stc, 
           InputDevice *i_d);
   ~Player();
    
    /*
     * Creates a clone of a Player object: involves cloning the ball,
     * the moving objects and active objects, so that Ogre & OgreNewt
     * contain copies of the objects.
     */
    Player *clone(Ogre::SceneManager *scene_mgr);

    void teleport(Ogre::Vector3, Ogre::Vector3, Ogre::Vector3);
    void update(Ogre::Real time);
    void usePod(bool u_p) { use_pod = u_p; }
    bool isUsingPod() { return use_pod; }
    void changeInputDevice(InputDevice *i_d);
    void initialiseDevice() { if(input_device) input_device->initialise(); }
    
    void finished() { player_finished = true; }
    bool isFinished() { return player_finished; }
    
    void setPlayState(PlayState *play_state);
    void reset();
    Ball *getBall() { return ball; }
    TeleportControl *getTeleportControl() { return teleport_control; }
    PickupControl *getPickupControl() { return pickup_control; }
    std::vector<MovingObject*> *getMovingObjects() { return &moving_objects; }
    int getID() { return ID; }
    bool isMainPlayer() { return main; }
    bool isTeleporting() { return teleporting; }
    void setMainPlayer(bool m) { main = m; }
    InputDevice *getInputDevice() { return teleporting ? temp : input_device; }
    std::vector<GravityState> getReplay() { return recorder->getReplay(); }
    void setInvert(bool i);
    void setSensitive(bool s);
    void setSpeed(bool s);

    // Replays
    void startRecording();
    void stopRecording();
    void addRecordingState(Ogre::Real time_increment);
	std::string saveReplay();
    std::string getReplayFilename() { return replay_file; }

    // Sessions
    void setSession(GameSession *s) { session = s; }
    GameSession *getSession() { return session; }
    
    // set visibility
    void show();
    void hide();
    bool isVisible() { return visible; }

    static int nextPlayerID;
    
private:
    bool player_finished;
    int ID;
    bool main;
    bool teleporting;
    float teleport_time_left;
    Ogre::Radian teleport_rotation;
    InputDevice *input_device, *temp;
    ReplayRecorder *recorder;
    Ball *ball;
	TeleportControl *teleport_control;
    PickupControl* pickup_control;
    ScoreObjectControl *score_object_control;
    ScoreToppleControl *score_topple_control;
    std::vector<MovingObject*> moving_objects;
    std::vector<OgreNewt::Body*> active_objects;
    bool use_pod;
    std::string replay_file;
    bool recording;
    bool invert, sensitive, speed;
    GameSession *session;
    bool visible;
} ;

#endif
